package com.qm.console.controller.hook.filter.param;

import com.qm.console.component.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;

@WebFilter(filterName = "paramFilter",  urlPatterns = "/*")
@Order(9999)
public class ParamsFilter implements Filter, HandshakeInterceptor {

    private final Logger Log = LoggerFactory.getLogger(this.getClass());
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PATCH = "PATCH";
    private static final String METHOD_PUT = "PUT";


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        BodyReaderHttpServletRequestWrapper servletRequest = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
        BodyReaderHttpServletResponseWrapper servletResponse = new BodyReaderHttpServletResponseWrapper((HttpServletResponse) response);
        request = servletRequest;
        response = servletResponse;
        //addCrossDomain(servletResponse);

        String method = servletRequest.getMethod();
        String uid = strDeal(servletRequest.getHeader("uid"));
        String token = strDeal(servletRequest.getHeader("token"));
        String ip = IpUtil.getIpAddr(servletRequest);
        String url = getQueryUrl(servletRequest);
        String bodyStr = "";
        if (METHOD_PUT.equals(method)
                || METHOD_POST.equals(servletRequest.getMethod())
                || METHOD_PATCH.equals(servletRequest.getMethod())) {
            bodyStr = servletRequest.getBodyString();
        }
        long time = System.currentTimeMillis();
        Log.info(String.format("[request] <%s>, url:<%s>,ip:<%s>, body:<%s>, uid:<%s>, token:<%s>", method, url, ip, bodyStr, uid, token));
        chain.doFilter(request, response);
        long cost = System.currentTimeMillis() - time;

        Log.info("[response] costTime<{}>, content:{}",cost,servletResponse.getResult());
    }

    private void addCrossDomain(HttpServletResponse response) {
        ((HttpServletResponse)response).setHeader("Access-Control-Allow-Origin", "*");
        ((HttpServletResponse)response).setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        ((HttpServletResponse)response).setHeader("Access-Control-Max-Age", "3600");
        ((HttpServletResponse)response).setHeader("Access-Control-Allow-Headers", "uid,userId, token, bundleId, serverVersion, Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
        ((HttpServletResponse)response).setHeader("Access-Control-Allow-Credentials","true");
    }

    private String strDeal(String str) {
        return Optional.ofNullable(str).orElse("");
    }

    private String getQueryUrl(HttpServletRequest servletRequest) {
        return servletRequest.getRequestURL() +
                (servletRequest.getQueryString() == null ? "" : ( "?" + servletRequest.getQueryString()));
    }


    @Override
    public void destroy() {

    }

    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {

        Log.info("socket connect");
        if (serverHttpRequest instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) serverHttpRequest;
            HttpSession session = servletRequest.getServletRequest().getSession(false);
            if (session != null) {
                String userName = (String) session.getAttribute("user");
                if(userName == null){
                    userName = "WEBSOCKET_USERNAME_IS_NULL";
                }
                map.put("user",userName);
            }
        }
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {

    }
}
